﻿
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Web;

namespace CS
{
    /// <summary>
    ///  将HttpContent里的Request里的相关集合转换为Param对象集合
    ///  参数处理模块:Ver:0.11
    /// </summary>
    /// 
    /// <description class = "CS.HttpParamHelper">
    ///   2010-02-04      增加期望捕获的枚举，降低不必的内存损耗
    ///   2010-02-05      增加IEnumerable给HttpParamCollection
    /// </description>
    /// 
    /// <history>
    ///   2010-3-3 18:14:33 , zhouyu ,  创建	     
    ///  </history>
    public sealed class HttpParamHelper
    {

        #region 只读的变量
        /// <summary>
        /// 所有客户端传参键值集合
        /// 在下面的三种情况下加上了ServerVariables键值对
        /// </summary>
        readonly HttpParamCollection _param;

        /// <summary>
        /// Http上下文
        /// </summary>
        readonly HttpContext _httpContext;
        /// <summary>
        /// URL字符串查询对像键值集合
        /// </summary>
        readonly HttpParamCollection _queryString;
        /// <summary>
        /// Form  键值集合
        /// </summary>
        readonly HttpParamCollection _form;
        /// <summary>
        /// Cookie 字典键值集合
        /// </summary>
        readonly HttpCookieParamCollection _cookie;


        readonly bool _isParamsValid;
        /// <summary>
        /// HttpContent里的Request不为空时有效
        /// </summary>
        readonly bool _isRequestValid;
        readonly bool _isQueryStringValid;
        readonly bool _isFormValid;
        readonly bool _isCookieValid;
        
        #endregion

        /// <summary>
        /// 使用 HttpContext.Current 初始化 HttpParamHelper 对象
        /// </summary>
        public HttpParamHelper(): this(HttpContext.Current)
        { }

        /// <summary>
        /// 增加型构造[避免实例化用不到的客户端变量键值集合]。
        /// </summary>
        /// <param name="type"></param>
        /// <exception cref="NullReferenceException">如果捕获设定以外的对象会抛出未引用的异常</exception>
        public HttpParamHelper(HttpParamNeedType type) : this(HttpContext.Current,type)
        {}

        /// <summary>
        /// 使用指定的 HttpContext 对象初始化 HttpParamHelper 对象.
        /// </summary>
        /// <param name="content">Http上下文</param>
        public HttpParamHelper(HttpContext content)
        {
            _httpContext = content;
            _isRequestValid = _httpContext.Request != null;
            _isQueryStringValid = _isRequestValid && this._httpContext.Request.QueryString != null;
            _isFormValid = _isRequestValid && this._httpContext.Request.Form != null;
            _isCookieValid = _isRequestValid && this._httpContext.Request.Cookies != null;
            
            _isParamsValid = _isRequestValid && this._httpContext.Request.Params != null;
            if (_isQueryStringValid)
                _queryString = new HttpParamCollection(this._httpContext.Request.QueryString);
            if (_isFormValid)
                _form = new HttpParamCollection(this._httpContext.Request.Form);
            if (_isCookieValid)
                _cookie = new HttpCookieParamCollection(this._httpContext.Request.Cookies);

            if (_isParamsValid)
                _param = new HttpParamCollection(this._httpContext.Request.Params);
        }

        /// <summary>
        /// 增加型构型
        /// </summary>
        /// <param name="content">Http上下文</param>
        /// <param name="type">需要捕获的HttpParam</param>
        /// <exception cref="NullReferenceException">如果捕获设定以外的对象会抛出未引用的异常</exception>
        public HttpParamHelper(HttpContext content,HttpParamNeedType type)
        {
            _httpContext = content;
            _isRequestValid = _httpContext.Request != null;

            _isQueryStringValid = _isRequestValid && this._httpContext.Request.QueryString != null;
            _isFormValid = _isRequestValid && this._httpContext.Request.Form != null;
            _isParamsValid = _isRequestValid && this._httpContext.Request.Params != null;
            _isCookieValid = _isRequestValid && this._httpContext.Request.Cookies != null;
            if (_isQueryStringValid && HttpParamNeedType.QueryString == (HttpParamNeedType.QueryString & type))
                _queryString = new HttpParamCollection(this._httpContext.Request.QueryString);
            if (_isFormValid && HttpParamNeedType.Form == (HttpParamNeedType.Form & type))
                _form = new HttpParamCollection(this._httpContext.Request.Form);
            if (_isCookieValid && HttpParamNeedType.Cookie == (HttpParamNeedType.Cookie & type))
                _cookie = new HttpCookieParamCollection(this._httpContext.Request.Cookies);

            if (_isParamsValid && HttpParamNeedType.Params == (HttpParamNeedType.Params & type))
                _param = new HttpParamCollection(this._httpContext.Request.Params);

        }

        /// <summary>
        /// HttpContext 对象
        /// </summary>
        internal HttpContext Context
        {
            get { return _httpContext; }
        }

        /// <summary>
        /// 带有Index与Name索引的HttpParamCollection
        /// </summary>
        public HttpParamCollection QueryString
        {
            get { return _queryString; }
        }

        /// <summary>
        /// 带有Index与Name索引的HttpParamCollection
        /// </summary>
        /// <example>HttpParamHelper().Form["inputText"].ToString();//返回的是一个HttpParam对象</example>
        public HttpParamCollection Form
        {
            get { return _form; }
        }
        
        /// <summary>
        /// 带有Index与Name索引的HttpCookieParamCollection
        /// </summary>
        public HttpCookieParamCollection Cookies
        {
            get { return _cookie; }
        }

        /// <summary>
        /// 带有Index与Name索引的HttpParamCollection
        /// </summary>
        public HttpParamCollection Params
        {
            get { return _param; }
        }

        ///<summary>
        ///</summary>
        ///<param name="index"></param>
        public ParamMethod this[int index]
        {
            get { return _param[index]; }
        }

        ///<summary>
        ///</summary>
        ///<param name="name"></param>
        public ParamMethod this[string name]
        {
            get { return _param[name]; }
        }
        
        #region IHttpParamCollection 无用

        ///// <summary>
        ///// HttpParamCollection 索引集合
        ///// </summary>
        //public interface IHttpParamCollection
        //{
        //    ///<summary>
        //    /// Index索引
        //    ///</summary>
        //    ///<param name="index"></param>
        //    HttpParamMethod this[int index]
        //    {
        //        get;
        //    }

        //    ///<summary>
        //    /// Name索引
        //    ///</summary>
        //    ///<param name="name"></param>
        //    HttpParamMethod this[string name]
        //    {
        //        get;
        //    }
        //}

        #endregion

        #region HttpCookieParam & HttpCookieParamCollection
        
        ///<summary>
        /// Cookie专用的HttpParam 
        ///</summary>
        public sealed class HttpCookieParam
        {
            readonly HttpCookie cookie;
            readonly int _index;
            readonly string _key;

            internal HttpCookieParam(int index, string key, HttpCookie cookie)
            {
                this._index = index;
                this._key = key;
                this.cookie = cookie;
            }

            ///<summary>
            /// Cookie是否存在
            ///</summary>
            public bool HasValue
            {
                get { return cookie != null; }
            }


            ///<summary>
            /// 获取Index索引中的Cookie值的HttpParamMethod
            ///</summary>
            ///<param name="i">Index索引</param>
            public ParamMethod this[int i]
            {
                get { return new ParamMethod(i, cookie.Values[i]); }
            }

            ///<summary>
            ///  获取Name索引中的Cookie值的HttpParamMethod
            ///</summary>
            ///<param name="name">Name索引</param>
            public ParamMethod this[string name]
            {
                get { return new ParamMethod(name, cookie[name]); }
            }

            ///<summary>
            /// 根据Index或者Cookie的Key值返回HttpParamMethod
            ///</summary>
            public ParamMethod Value
            {
                get 
                {
                    return _index > -1 ? new ParamMethod(_index, cookie.Value) : new ParamMethod(_key, cookie.Value);
                }
            }
        }
        
        ///<summary>
        /// HttpContext里的 Cookie 参数键值的集合[Cookie专用]
        ///</summary>
        public sealed class HttpCookieParamCollection
        {
            readonly HttpCookieCollection collection;

            internal HttpCookieParamCollection(HttpCookieCollection collection)
            {
                this.collection = collection;
            }

            ///<summary>
            /// HttpCookieParam的Index索引
            ///</summary>
            ///<param name="i">Index</param>
            public HttpCookieParam this[int i]
            {
                get { return new HttpCookieParam(i, null, collection[i]); }
            }

            ///<summary>
            /// HttpCookieParam的Name索引
            ///</summary>
            ///<param name="name">Name</param>
            public HttpCookieParam this[string name]
            {
                get { return new HttpCookieParam(-1, name, collection[name]); }
            }
        }

        #endregion

        #region HttpParamCollection

        /// <summary>
        /// HttpContext里的 QueryString、Form、ServerVariable 参数键值的集合
        /// </summary>
        public sealed class HttpParamCollection : IEnumerable
        {
            /// <summary>
            /// 键值集合
            /// </summary>
            readonly NameValueCollection collection;

            /// <summary>
            /// 构造:给键值对赋值
            /// </summary>
            /// <param name="collection"></param>
            internal HttpParamCollection(NameValueCollection collection)
            {
                this.collection = collection;
            }

            ///<summary>
            /// 根据Index索引返回HttpParamMethod
            ///</summary>
            ///<param name="i">Index</param>
            public ParamMethod this[int i]
            {
                get { return new ParamMethod(i, collection[i]); }
            }

            ///<summary>
            /// 根据Name索引返回HttpParamMethod
            ///</summary>
            ///<param name="name">Name</param>
            public ParamMethod this[string name]
            {
                get { return new ParamMethod(name, collection[name]); }
            }

            ///<summary>
            /// 捕获集合中的对应枚举值的类型，并转换为枚举值[注:针对有Flag的枚举:用于权限]
            ///</summary>
            ///<typeparam name="T"></typeparam>
            ///<returns></returns>
            public Param<T> ToEnum<T>()
            {
                var name = Enum.GetNames(typeof(T));
                var value = String.Empty;
                for (var i = 0; i < name.Length; i++)
                {
                    var key = name[i];
                    var item = collection[key];
                    if (item != null && item == "1")
                        value += key + ",";
                }
                return new Param<T>(typeof(T).ToString(), ParamTool.Enum<T>(value.TrimEnd(',')));
            }

            ///<summary>
            /// Todo:?
            ///</summary>
            ///<param name="defaultValue">默认的枚举的Int32值</param>
            ///<typeparam name="T">枚举的类型</typeparam>
            ///<returns>期望的枚举Int32值</returns>
            public int ToEnum<T>(int defaultValue)
            {
                var typeName = typeof(T).Name;
                var values = (int[])Enum.GetValues(typeof(T));
                foreach (var i in values)
                {
                    var option = collection[typeName + "_" + i] == "1";
                    //value.SetOption(i, );
                    if (option)
                        defaultValue |= i;
                    else
                        defaultValue &= ~i;
                }
                return defaultValue;
            }


            #region IEnumerator

            ///<summary>
            /// 实现接口
            ///</summary>
            ///<returns></returns>
            public IEnumerator GetEnumerator()
            {
                foreach (var c in collection)
                {
                    yield return c;
                }
            }

            #endregion

        }

        #endregion
    }
    
    /// <summary>
    /// 期望捕获客户端参数的类型[为了提高性能，不需要的键值变量不转换为HttpParma]
    /// </summary>
    [Flags]
    public enum HttpParamNeedType
    {
        /// <summary>
        /// 捕获URL
        /// </summary>
        QueryString=1,

        /// <summary>
        /// 捕获表单
        /// </summary>
        Form = 2,

        /// <summary>
        /// 捕获Cookie
        /// </summary>
        Cookie = 4,

        /// <summary>
        /// 捕获Params
        /// </summary>
        Params = 8,

        /// <summary>
        /// 全部捕获
        /// </summary>
        All = QueryString|Form|Cookie|Params,


    }

}
